import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入gui.js的一个类GUI
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
/**
 * 创建3D场景
 */
// 创建3D场景对象Scene
const scene = new THREE.Scene();
// 创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(20, 20, 20);
// 创建一个材质对象Material, 使用受光照的材质，需要添加光源
const material = new THREE.MeshLambertMaterial({
  color: '#0080FF', //0xff0000设置材质颜色为红色
  transparent: true, // 开启半透明
  opacity: 0.5, // 设置透明度
  // side: THREE.DoubleSide // 设置两面可见
});
// 创建一个网格模型，表示生活中的物体, 传入参数geometry、材质material
const mesh = new THREE.Mesh(geometry, material);
// 设置物体的位置
mesh.position.set(0, 0, 0);
// 把网格模型mesh添加到三维场景scene中。
scene.add(mesh);

// 创建三维坐标系
const axesHelper = new THREE.AxesHelper(80);
scene.add(axesHelper); // 三维坐标添加到场景中

// 创建光源对象，点光源，两个参数分别表示光源颜色和光照强度
const pointLight = new THREE.PointLight(0xffffff, 20);
pointLight.decay = 0.0; // 禁止光源衰减
pointLight.position.set(400, 200, 300); // 设置光源的位置
scene.add(pointLight); // 光源添加到场景中

// 可视化点光源
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 10)
// scene.add(pointLightHelper)

// 添加环境光，环境光没有方向
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);

// 添加平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(50, 100, 60);
// 方向光指向对象网格模型mesh，可以不设置，默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);

// 可视化平行光
const dirLightHelper = new THREE.DirectionalLightHelper(
  directionalLight,
  5,
  0xffffff
);
scene.add(dirLightHelper);

/**
 * 透视投影相机设置
 */
// 定义相机渲染输出的画布尺寸
// const width = 800
// const height = 500
// 设置全屏画布宽高
const width = window.innerWidth;
const height = window.innerHeight;
// 实例化一个透视投影相机对象, 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000：远裁截面
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200);
// 相机观察目标, 物体的位置
camera.lookAt(mesh.position);

/**
 * 3D渲染器
 */
// WebGL渲染器WebGLRenderer,通过WebGL渲染器WebGLRenderer可以实例化一个WebGL渲染器对象
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); // 设置渲染器的大小
renderer.render(scene, camera); // 执行渲染操作
const webglId = document.getElementById('webgl');
webglId.appendChild(renderer.domElement);

// 创建一个相机控件OrbitControls对象
const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
controls.addEventListener('change', function () {
  renderer.render(scene, camera); // 重新执行渲染操作
});

// 动画渲染循环
function render() {
  // 周期性执行渲染操作，更新canvas画布上的内容
  renderer.render(scene, camera);
  // 每次绕y轴旋转0.01度
  mesh.rotateY(0.01);
  //请求再次执行渲染函数render，渲染下一帧
  requestAnimationFrame(render);
}
render();

// Canvas设置动态画布宽高，动态变化画布宽高，onresize 事件会在窗口被调整大小时发生
window.onresize = function () {
  // 重置渲染器输出画布canvas尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 全屏情况下：设置观察范围长宽比aspect为窗口宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
  // 但是不会每渲染一帧，就通过相机的属性计算投影矩阵(节约计算资源)
  // 如果相机的一些属性发生了变化，需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
  camera.updateProjectionMatrix();
};

/**
 * gui图形界面
 */
// 实例化GUI对象
const gui = new GUI();

// 设置样式
gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';

//控制光照强度
gui
  .add(ambient, 'intensity', 0, 2)
  .name('环境光强度')
  .onChange(function (value) {
    mesh.intensity = value;
  });

// 控制xyz坐标
gui
  .add(mesh.position, 'x', 0, 400)
  .name('x轴坐标')
  .onChange(function (value) {
    mesh.position.x = value;
  });
gui.add(mesh.position, 'y', 0, 400).name('y轴坐标').onChange(function(){
  console.log()
});
gui.add(mesh.position, 'z', 0, 400).name('z轴坐标');